home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr42
/
vocshow2.zip
/
COMPRESS.PKG
< prev
next >
Wrap
Text File
|
1993-06-08
|
5KB
|
120 lines
-- Copyright 1992 by Tom Moran. May be used by anyone for any purpose.
with SB_Samples,
System;
use SB_Samples;
package body Compress is
-- sound sample levels range from 0 .. 255, so differences between
-- successive samples can range from -255 .. +255
type Differences is range - 255 .. 255;
subtype Levels is Differences range 0 .. 255;
type Adaptive_Step_Indices is range 0 .. 3;
for Adaptive_Step_Indices'Size use 2;
Doubled_Step_Size: constant array (Adaptive_Step_Indices) of Differences
:= (2, 5, 10, 20); -- steps are 1 2.5 5 10
-- max of 7 steps at max of 10 units/step
type Delta_Approxs is range - 70 .. 70;
for Delta_Approxs'Size use 8;
-- given a current difference and a current adaptive step size,
-- we need to know what 4 bit packed nibble to emit, by what delta
-- that changes the current approximation, and what the new step
-- size will be. The answers are packed into 16 bits so we need a
-- lookup array of 511 differences *4 step sizes*2 bytes = 4088 bytes
type Process_One_Results is
record
Delta_Approx : Delta_Approxs;
Nibble : SB_Samples.Packed_Sound_Nibbles;
New_Step_Index: Adaptive_Step_Indices;
end record;
for Process_One_Results use
record
Delta_Approx at 0 range 0 .. 7;
Nibble at 0 range 8 .. 11;
New_Step_Index at 0 range 12 .. 13;
end record;
for Process_One_Results'Size use 16;
Process_One_Result_Array: array (Differences, Adaptive_Step_Indices)
of Process_One_Results;
Current_Approx: Levels := 128;
Current_Step_Index: Adaptive_Step_Indices := Adaptive_Step_Indices'First;
function Min(Left, Right : in Integer) return Integer is
begin if Left < Right then return Left;else return Right;end if;end Min;
procedure Pack(Unpacked_Source_Address:in System.Address;
Sound_Length :in Natural;
Packed_Target : out SB_Samples.Packed_Sounds) is
pragma All_Checks(Off); -- allow garbage in to produce garbage out
Unpacked_Source:SB_Samples.Unpacked_Sounds
-- static array bounds generate better code with my compiler
(SB_Samples.Sound_Indices);
for Unpacked_Source use at Unpacked_Source_Address;
J : Integer := Unpacked_Source'First;
Pair_Count : constant Integer:=Min(Sound_Length/2,Packed_Target'Length);
This_Result : Process_One_Results;
Left_Nibble,
Right_Nibble: SB_Samples.Packed_Sound_Nibbles;
begin
for I in Packed_Target'First .. Packed_Target'First+Pair_Count-1 loop
This_Result
:= Process_One_Result_Array(Levels(Unpacked_Source(J))-Current_Approx,
Current_Step_Index);
Current_Approx := Current_Approx + Differences(This_Result.Delta_Approx);
Left_Nibble := This_Result.Nibble;
This_Result
:=Process_One_Result_Array(Levels(Unpacked_Source(J+1))-Current_Approx,
This_Result.New_Step_Index);
Current_Approx := Current_Approx + Differences(This_Result.Delta_Approx);
Right_Nibble := This_Result.Nibble;
Current_Step_Index := This_Result.New_Step_Index;
Packed_Target(I) := Packed_Sound_Pairs(Left_Nibble)*16
+Packed_Sound_Pairs(Right_Nibble);
J := J + 2;
end loop;
end Pack;
procedure Initialize is -- fill in process_one_result_array
Magnitude: Differences range 0 .. Differences'Last;
This_Result: Process_One_Results;
begin
for Step_Index in Adaptive_Step_Indices loop
for Diff in Differences loop
Magnitude := (abs (Diff) * 2) / Doubled_Step_Size(Step_Index);
if Magnitude > 7 then
Magnitude := 7;
end if;
This_Result.Delta_Approx
:= Delta_Approxs((Magnitude*Doubled_Step_Size(Step_Index))/2);
This_Result.Nibble := SB_Samples.Packed_Sound_Nibbles(Magnitude);
if Diff < 0 then
This_Result.Delta_Approx := - This_Result.Delta_Approx;
This_Result.Nibble := This_Result.Nibble + 8;
end if;
This_Result.New_Step_Index := Step_Index;
if Magnitude = 0 then
if Step_Index > Adaptive_Step_Indices'First then
This_Result.New_Step_Index
:= Adaptive_Step_Indices'Pred(Step_Index);
end if;
elsif Magnitude > 4 then
if Step_Index < Adaptive_Step_Indices'Last then
This_Result.New_Step_Index
:= Adaptive_Step_Indices'Succ(Step_Index);
end if;
end if;
Process_One_Result_Array(Diff, Step_Index) := This_Result;
end loop; -- differences
end loop; -- adaptive_step_indices
end Initialize;
begin
Initialize;
end Compress;